package com.neusoft.work.service.impl;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.neusoft.work.dao.BedAssignmentDao;
import com.neusoft.work.dao.BedInfoDao;
import com.neusoft.work.dao.CareLevelDao;
import com.neusoft.work.dao.CheckOutRegistrationDao;
import com.neusoft.work.dao.CustomerCareLevelDao;
import com.neusoft.work.dao.CustomerDao;
import com.neusoft.work.dao.HealthManagerCustomerDao;
import com.neusoft.work.dao.UserDao;
import com.neusoft.work.dto.CheckOutRegistrationDto;
import com.neusoft.work.dto.ClientInfoDTO;
import com.neusoft.work.po.BedAssignment;
import com.neusoft.work.po.BedInfo;
import com.neusoft.work.po.CareLevel;
import com.neusoft.work.po.CheckOutRegistration;
import com.neusoft.work.po.Customer;
import com.neusoft.work.po.CustomerCareLevel;
import com.neusoft.work.po.HealthManagerCustomer;
import com.neusoft.work.po.PageResponseBean;
import com.neusoft.work.po.ResponseBean;
import com.neusoft.work.po.User;
import com.neusoft.work.service.CheckOutRegistrationService;
import com.neusoft.work.util.PaginationUtil;

@Service
public class CheckOutRegistrationServiceImpl implements CheckOutRegistrationService {

    @Autowired
    private CheckOutRegistrationDao dao;
    
    @Autowired
    private CustomerDao cd;
    
    @Autowired
    private BedInfoDao bedInfoDao;

	@Autowired
	private HealthManagerCustomerDao healthManagerCustomerDao;

	@Autowired
	private CustomerCareLevelDao customerCareLevelDao;

    @Autowired
    private BedAssignmentDao bad;
    @Autowired
    private CareLevelDao careLevelDao;
    @Autowired
    private UserDao userDao;



    @Override
    public PageResponseBean<List<CheckOutRegistrationDto>> queryAll(String name, Long cur, Long number) {
        // 1. 根据 name 查 customerIds
        List<Integer> customerIds;
        if (name != null && !name.trim().isEmpty()) {
            List<Customer> customers = cd.selectList(
                new QueryWrapper<Customer>()
                    .like("name", name)
                    .select("id"));
            if (customers.isEmpty()) {
                return new PageResponseBean<>(500, "无数据");
            }
            customerIds = customers.stream()
                                   .map(Customer::getId)
                                   .collect(Collectors.toList());
        } else {
            customerIds = null;
        }

        // 2. 分页查询 CheckOutRegistration
        Page<CheckOutRegistration> page = new Page<>(cur, number);
        QueryWrapper<CheckOutRegistration> qw = new QueryWrapper<>();
        if (customerIds != null && !customerIds.isEmpty()) {
            qw.in("customerId", customerIds);
        }
        IPage<CheckOutRegistration> result = dao.selectPage(page, qw);

        List<CheckOutRegistration> list = result.getRecords();
        long total = result.getTotal();
        PageResponseBean<List<CheckOutRegistrationDto>> rb;

        if (total > 0) {
        	// 3. 查询所有相关的 customerName
        	List<Integer> custIds = list.stream()
        	    .map(CheckOutRegistration::getCustomerId)
        	    .filter(Objects::nonNull)
        	    .distinct()
        	    .collect(Collectors.toList());

        	// 初始化为一个可变的 Map，一定要这样 new 出来，不能用 Collections.emptyMap()
        	Map<Integer, String> custMap = new HashMap<>();

        	if (!custIds.isEmpty()) {
        	    // 往同一个 custMap 里 put，而不是重新赋值
        	    cd.selectBatchIds(custIds).forEach(c -> 
        	        custMap.put(c.getId(), c.getName())
        	    );
        	}

        	// 4. 查询所有相关的 operatorUserName，同样思路
        	List<Integer> userIds = list.stream()
        	    .map(CheckOutRegistration::getOperatorUserId)
        	    .filter(Objects::nonNull)
        	    .distinct()
        	    .collect(Collectors.toList());

        	Map<Integer, String> userMap = new HashMap<>();

        	if (!userIds.isEmpty()) {
        	    userDao.selectBatchIds(userIds).forEach(u ->
        	        userMap.put(u.getId(), u.getRealName())
        	    );
        	}

        	// 5. 封装 DTO
        	List<CheckOutRegistrationDto> dtoList = list.stream().map(entity -> {
        	    CheckOutRegistrationDto dto = new CheckOutRegistrationDto();
        	    BeanUtils.copyProperties(entity, dto);
        	    dto.setCustomerName(custMap.get(entity.getCustomerId()));      // 正常工作
        	    dto.setOperatorUserName(userMap.get(entity.getOperatorUserId()));
        	    return dto;
        	}).collect(Collectors.toList());

            rb = new PageResponseBean<>(dtoList);
            rb.setTotal(total);
        } else {
            rb = new PageResponseBean<>(500, "no data");
        }
        return rb;
    }


	@Override
	public ResponseBean<Integer> add(CheckOutRegistration record) {
		// TODO Auto-generated method stub
        // 直接按主键更新，返回影响行数
        int rows = dao.insert(record);
        if (rows > 0) {
            // 更新成功
            return new ResponseBean<>(rows);
        } else {
            // 更新失败
            return new ResponseBean<>(500, "插入失败");
        }
	}

	@Override
	public ResponseBean<Integer> update(CheckOutRegistration record) {
		// TODO Auto-generated method stub
        // 直接按主键更新，返回影响行数
        int rows = dao.updateById(record);
        if (rows > 0) {
            // 更新成功
            return new ResponseBean<>(rows);
        } else {
            // 更新失败
            return new ResponseBean<>(500, "更新失败，没有找到对应记录");
        }
	}

	@Override
	public ResponseBean<Integer> delete(Integer id) {
		// TODO Auto-generated method stub
        // 按主键删除，返回影响行数
        int rows = dao.deleteById(id);
        if (rows > 0) {
            // 删除成功
            return new ResponseBean<>(rows);
        } else {
            // 删除失败
            return new ResponseBean<>(500, "删除失败，没有找到对应记录");
        }
	}

	@Override
	public ResponseBean<Integer> approve(Integer id, Integer approveStatus, Integer operatorUserId) {
	    // 1. 查出退住申请记录
	    CheckOutRegistration rec = dao.selectById(id);
	    if (rec == null) {
	        return new ResponseBean<>(500, "退住申请记录不存在");
	    }

	    // 2. 更新审批状态、审批人、审批时间
	    rec.setApproveStatus(approveStatus);   // 1=通过，2=拒绝
	    rec.setOperatorUserId(operatorUserId);
	    String now = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
	    rec.setApproveTime(now);
	    int rows = dao.updateById(rec);

	    // 3. 如果审批通过且类型为正常退住（0）或死亡退住（1）
	    if (rows > 0 && approveStatus == 1 && (rec.getCheckOutType() == 0 || rec.getCheckOutType() == 1)) {
	        Integer customerId = rec.getCustomerId();

	        // 3.1 查询当前客户的床位分配记录
	        BedAssignment assign = bad.selectOne(new QueryWrapper<BedAssignment>()
	            .eq("customerId", customerId)
	            .eq("isDeleted", false)
	            .last("LIMIT 1"));

	        if (assign != null && assign.getBedNumber() != null) {
	            // 3.2 修改床位状态为“可用” (status = 1 表示可用)
	            bedInfoDao.update(null,
	                new UpdateWrapper<BedInfo>()
	                    .eq("bedNumber", assign.getBedNumber())
	                    .set("status", 1)
	            );

	            // 3.3 将床位分配记录置为历史：设置结束时间和标记已删除
	            bad.update(null,
	                new UpdateWrapper<BedAssignment>()
	                    .eq("id", assign.getId())
	                    .set("assignEndTime", now)
	                    .set("isDeleted", true)
	            );
	        }

	        // 3.4 将客户标记为已删除
	        cd.update(null,
	            new UpdateWrapper<Customer>()
	                .eq("id", customerId)
	                .set("isDeleted", true)
	        );

	        // 3.5 删除该客户的护工分配记录
	        healthManagerCustomerDao.delete(
	            new QueryWrapper<HealthManagerCustomer>()
	                .eq("customerId", customerId)
	        );
	    }

	    return rows > 0
	        ? new ResponseBean<>(rows)
	        : new ResponseBean<>(500, "审批失败");
	}


	
	

	@Override
	public PageResponseBean<List<ClientInfoDTO>> searchClient(Integer healthManagerId, String clientName, Long cur, Long number) {
		List<HealthManagerCustomer> healthManagerCustomers = healthManagerCustomerDao.selectList(
				new QueryWrapper<HealthManagerCustomer>()
						.eq("healthManagerId", healthManagerId)
		);
		
		if (healthManagerCustomers.isEmpty()) {
		    // 没有任何管理的客户，直接返回空分页
		    PageResponseBean<List<ClientInfoDTO>> emptyRb = new PageResponseBean<>(Collections.emptyList());
		    emptyRb.setTotal(0);
		    return emptyRb;
		}
		
		if(clientName != null && !clientName.trim().isEmpty()) {
			Customer client = cd.selectOne(new QueryWrapper<Customer>()
					.like("name", clientName));
			if(client == null){
				return new PageResponseBean<>(500,"无数据");
			}
			Integer clientId = client.getId();
			Integer flag = 0;
			for(HealthManagerCustomer hmc : healthManagerCustomers) {
				if(hmc.getCustomerId().equals(clientId)) {
					flag = 1;
					break;
				}
			}
			if(flag == 1) {
				ClientInfoDTO clientInfoDTO = new ClientInfoDTO();
				clientInfoDTO.setId(client.getId());
				clientInfoDTO.setName(client.getName());
				clientInfoDTO.setGender(client.getGender());
				clientInfoDTO.setAge(client.getAge());
				clientInfoDTO.setRoomNumber(client.getRoomNumber());
				clientInfoDTO.setBedNumber(client.getBedNumber());

				CustomerCareLevel ccl = customerCareLevelDao.selectOne(
						new QueryWrapper<CustomerCareLevel>().eq("customerId", client.getId())
				);
				CareLevel careLevel;
				if(ccl != null) {
					careLevel = careLevelDao.selectById(ccl.getCareLevelId());
					clientInfoDTO.setCareLevelName(careLevel.getLevelName());
				}else{
					clientInfoDTO.setCareLevelName("");
				}

				List<ClientInfoDTO> clientInfoDTOS = new ArrayList<>();
				clientInfoDTOS.add(clientInfoDTO);

				PageResponseBean<List<ClientInfoDTO>> rb=null;
				rb=new PageResponseBean<>(clientInfoDTOS);
				rb.setTotal(1);
				return rb;
			}else{
				return null;
			}
		}else{
			List<Integer> clientsIds = new ArrayList<>();
			for(HealthManagerCustomer hmc : healthManagerCustomers) {
				clientsIds.add(hmc.getCustomerId());
			}
			List<Customer> clients = cd.selectBatchIds(clientsIds);
			List<ClientInfoDTO> clientInfoDTOS = clients.stream().map(p -> {
				ClientInfoDTO dto = new ClientInfoDTO();
				// 拷贝通用字段
				dto.setId(p.getId());
				dto.setName(p.getName());
				dto.setAge(p.getAge());
				dto.setRoomNumber(p.getRoomNumber());
				dto.setBedNumber(p.getBedNumber());
				dto.setGender(p.getGender());

				CustomerCareLevel ccl = customerCareLevelDao.selectOne(
						new QueryWrapper<CustomerCareLevel>().eq("customerId", p.getId())
				);

				if (ccl != null) {
					CareLevel careLevel = careLevelDao.selectById(ccl.getCareLevelId());
					dto.setCareLevelName(careLevel.getLevelName());
				} else {
					dto.setCareLevelName("");
				}
				return dto;
			}).collect(Collectors.toList());

			List<ClientInfoDTO> pageData = PaginationUtil.paginate(clientInfoDTOS, cur, number);

			PageResponseBean<List<ClientInfoDTO>> rb=new PageResponseBean<>(pageData);
			rb.setTotal(pageData.size());
			return rb;
		}
    }

	@Override
	public ResponseBean<Integer> checkOutRegister(CheckOutRegistration checkOutRegistration) {
		int rows = dao.insert(checkOutRegistration);
		if (rows > 0) {
			// 更新成功
			return new ResponseBean<>(rows);
		} else {
			// 更新失败
			return new ResponseBean<>(500, "插入失败");
		}
	}

	@Override
	public PageResponseBean<List<CheckOutRegistrationDto>> searchRegistration(Integer healthManagerId, String clientName, Long cur, Long number) {
	    List<HealthManagerCustomer> healthManagerCustomers = healthManagerCustomerDao.selectList(
	        new QueryWrapper<HealthManagerCustomer>().eq("healthManagerId", healthManagerId)
	    );

	    List<CheckOutRegistrationDto> resultList = new ArrayList<>();

	    if (clientName != null && !clientName.trim().isEmpty()) {
	        Customer client = cd.selectOne(new QueryWrapper<Customer>().eq("name", clientName));
	        if (client == null) return null;

	        Integer clientId = client.getId();
	        boolean matched = healthManagerCustomers.stream()
	            .anyMatch(hmc -> hmc.getCustomerId().equals(clientId));

	        if (matched) {
	            List<CheckOutRegistration> regList = dao.selectList(new QueryWrapper<CheckOutRegistration>().eq("customerId", clientId));
	            for (CheckOutRegistration reg : regList) {
	                CheckOutRegistrationDto dto = toDto(reg, client.getName());
	                resultList.add(dto);
	            }
	        } else {
	            return null;
	        }

	    } else {
	        List<Integer> clientIds = healthManagerCustomers.stream()
	            .map(HealthManagerCustomer::getCustomerId)
	            .collect(Collectors.toList());

	        List<Customer> customers = cd.selectBatchIds(clientIds);
	        Map<Integer, String> idToNameMap = customers.stream()
	            .collect(Collectors.toMap(Customer::getId, Customer::getName));

	        for (Integer clientId : clientIds) {
	            List<CheckOutRegistration> regList = dao.selectList(new QueryWrapper<CheckOutRegistration>().eq("customerId", clientId));
	            for (CheckOutRegistration reg : regList) {
	                String customerName = idToNameMap.get(reg.getCustomerId());
	                CheckOutRegistrationDto dto = toDto(reg, customerName);
	                resultList.add(dto);
	            }
	        }
	    }

	    // 分页
	    List<CheckOutRegistrationDto> pageData = PaginationUtil.paginate(resultList, cur, number);
	    PageResponseBean<List<CheckOutRegistrationDto>> rb = new PageResponseBean<>(pageData);
	    rb.setTotal(resultList.size());
	    return rb;
	}
	
	// 辅助方法：转换实体为 DTO，附带审批人姓名
	private CheckOutRegistrationDto toDto(CheckOutRegistration reg, String customerName) {
	    CheckOutRegistrationDto dto = new CheckOutRegistrationDto();
	    BeanUtils.copyProperties(reg, dto);
	    dto.setCustomerName(customerName);

	    if (reg.getOperatorUserId() != null) {
	        User user = userDao.selectById(reg.getOperatorUserId());
	        if (user != null) {
	            dto.setOperatorUserName(user.getRealName()); // 或 user.getUserName()
	        }
	    }

	    return dto;
	}


}